package com.kvn.interceptor;

import com.alibaba.druid.sql.ast.SQLStatement;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.kvn.config.ShardProperties;
import com.kvn.config.TableRule;
import com.kvn.strategy.ShardStrategy;
import com.kvn.strategy.ShardStrategyFactory;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.springframework.stereotype.Component;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Sql改写器
 * Created by wangzhiyuan on 2018/6/11
 */
@Component
public class SqlReseter {
    @Resource
    private ShardProperties shardProperties;
    @Resource
    private ShardStrategyFactory shardStrategyFactory;

    public Set<String> reset(List<SqlParserResult> sqlParserResults, List<SQLStatement> sqlStatements) {
        List<SQLStatement> newSQLStatementList = Lists.newArrayList(sqlStatements.get(0)); // sql可能从1条变成多条

        for (SqlParserResult parserResult : sqlParserResults) {
            TableRule tableRule = shardProperties.getTables().get(parserResult.getTableName());
            // 不是需要分表的表，continue
            if (tableRule == null) {
                continue;
            }

            // 不是分表字段，continue
            if (!parserResult.getColumn().equals(tableRule.getShardColum())) {
                continue;
            }

            // 处理每一条sql
            List<SQLStatement> sqlStatementsAfterConvert = Lists.newArrayList();
            for (SQLStatement statement : newSQLStatementList) {
                for (Object columnValue : parserResult.getColumnValues()) {
                    statement = obtainNewSql(columnValue, parserResult, tableRule, statement);
                    sqlStatementsAfterConvert.add(statement);
                }
            }
            newSQLStatementList = sqlStatementsAfterConvert;

        }

        Set<String> newSqlSet = Sets.newHashSet(Collections2.transform(newSQLStatementList, new Function<SQLStatement, String>() {
            public String apply(SQLStatement sqlStatement) {
                return sqlStatement.toString();
            }
        }));
        System.out.println("sqlAfterReset = [" + newSqlSet + "]");
        return newSqlSet;
    }

    private SQLStatement obtainNewSql(Object columnValue, SqlParserResult parserResult, TableRule tableRule, SQLStatement sqlStatement) {
        SQLStatement clone = sqlStatement.clone();
        ShardStrategy shardStrategy = shardStrategyFactory.findStragety(tableRule.getStrategy());
        String tableNumber = shardStrategy.decideTableName(columnValue, tableRule.getStrategy());
        TableNameModifier tnm = new TableNameModifier(parserResult.getTableName(), parserResult.getTableName() + "_" + tableNumber);
        clone.accept(tnm);
        return clone;
    }
}
